package translation;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class OneToOne implements RuleTypeConstants {
	//From Field
	private String fromXPath;
	private String fromRegEx = null;	
	private List<VarBinding> vb = null;
	
	//To field
	private String toXPath;	
	private String toRegEx = null;

	public OneToOne(String fromXPath, String toXPath) {
		this.fromXPath = fromXPath;
		this.toXPath = toXPath;
	}

	public OneToOne(String fromXPath, String fromRegEx, String toXPath,	String toRegEx) {
		this.fromXPath = fromXPath;
		this.fromRegEx = fromRegEx;
		this.toXPath = toXPath;
		this.toRegEx = toRegEx;
	}

	public String getFromXPath() {
		return fromXPath;
	}

	public void setFromXPath(String fromXPath) {
		this.fromXPath = fromXPath;
	}

	public String getFromRegEx() {
		return fromRegEx;
	}

	public void setFromRegEx(String fromRegEx) {
		this.fromRegEx = fromRegEx;
	}

	public String getToXPath() {
		return toXPath;
	}

	public void setToXPath(String toXPath) {
		this.toXPath = toXPath;
	}

	public String getToRegEx() {
		return toRegEx;
	}

	public void setToRegEx(String toRegEx) {
		this.toRegEx = toRegEx;
	}

	public List<VarBinding> getVariableBinding(){
		return vb;
	}
	public List<VarBinding> initVariableBinding(){
		vb = new ArrayList<VarBinding>();
		return vb;
	}
	public List<VarBinding> addVariableBinding(VarBinding v){
		if(vb == null)
			vb = new ArrayList<VarBinding>();
		vb.add(v);
		return vb;
	}
	
	public void removeVarBinding(int index){
		if(vb != null){
			vb.remove(index);
		}
	}
	
	public void removeVarBinding(VarBinding v){
		if(vb != null){
			vb.remove(v);
		}
	}

	/**
	 * Writes the OneToOne structure to a file
	 * @param output The file to 
	 */
	public void writeToXMLFile(File output){
		
		BufferedWriter bw = null;
		try {
			//Initialize output file
			if (!output.exists()) {
				output.createNewFile();
			}
			FileWriter fw = new FileWriter(output.getAbsoluteFile(),true); //append to existing file
			bw = new BufferedWriter(fw);
			
			//write basic tag
			bw.write(OneToOneStartingTag);
			
			//Variable Binding and from Regex not exists => SourceFieldType
			if(vb == null && fromRegEx == null){
				bw.write(SourceFieldTypeStart);
				bw.write(XPathExpressionStart + fromXPath + XPathExpressionTerminating);
			}
			else{
				//Variable Binding exists => FilteredSourceFieldType
				bw.write(FilteredSourceFieldTypeStart);
				bw.write(XPathExpressionStart + fromXPath + XPathExpressionTerminating);
				
				if(fromRegEx != null){						
					bw.write(FilteredWithRegexStart + fromRegEx + FilteredWithRegexTerminating);
				}	
				
				if(vb != null){
					for(VarBinding v : vb){
						bw.write(VariableBindingStart);
						if(v.getExplicitPrefixBinding() !=null){
							for(String s : v.getExplicitPrefixBinding()){
								bw.write(ExplicitPrefixBindingStart + s + ExplicitPrefixBindingTerminating);
							}
						}
						else if(v.getListBinding() != null){
							bw.write(ListBindingStart + v.getListBinding() + ListBindingTerminating);
						}
						else if(v.getExplicitPostfixBinding() != null){
							for(String s : v.getExplicitPostfixBinding()){
								bw.write(ExplicitPostfixBindingStart + s + ExplicitPostfixBindingTerminating);
							}
						}
						else if(v.getExplicitBinding() != null){
							bw.write(ExplicitBindingStart + v.getExplicitBinding() + ExplicitBindingTerminating);
						}
						bw.write(VariableBindingTerminating);
					}
				}
			}
			bw.write(TerminatingFromField);
			
			//To Regex not exists => TargetFieldType
			if(toRegEx == null){
				bw.write(TargetFieldTypeStart);
				bw.write(XPathExpressionStart + toXPath + XPathExpressionTerminating);
			}
			else{
				bw.write(FormattedTargetFieldTypeStart);
				bw.write(XPathExpressionStart + toXPath + XPathExpressionTerminating);
				bw.write(ReplaceWithRegExprStart + toRegEx + ReplaceWithRegExprTerminating);
			}
			bw.write(TargetFieldTypeClosing);
			
			//Write closing tag
			bw.write(TerminatingTag);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally{
			try {
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Converts the object to a OneToOneFieldTranslationType and returns it
	 * @return The converted element
	 */
	public OneToOneFieldTranslationType toOneToOneFieldTranslationType(){
		ObjectFactory of = new ObjectFactory();
		
		//Create object
		OneToOneFieldTranslationType otoft = new OneToOneFieldTranslationType();
		
		//From field
		if(fromRegEx == null && vb == null){
			SourceFieldType st = of.createSourceFieldType();
			st.setXPathExpression(fromXPath);
			otoft.setFromField(st);
		}
		else{
			FilteredSourceFieldType fst = of.createFilteredSourceFieldType();
			fst.setXPathExpression(fromXPath);
			fst.setFilterWithRegExpr(fromRegEx);
			if(vb != null)
				for(VarBinding v : vb)
					fst.getVariableBinding().add(v.toVariableBinding());
			
			otoft.setFromField(fst);
		}		
		
		//To field
		if(toRegEx == null){
			TargetFieldType tft = of.createTargetFieldType();
			tft.setXPathExpression(toXPath);
			otoft.setToField(tft);
		}
		else{
			FormattedTargetFieldType ftft = of.createFormattedTargetFieldType();
			ftft.setXPathExpression(toXPath);
			ftft.setReplaceWithRegExpr(toRegEx);
			otoft.setToField(ftft);
		}
		
		return otoft;		
	}
}
